package com.wmh.baseservice.common.utils;

import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.*;

import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.qrcode.QRCodeMultiReader;
import com.google.zxing.qrcode.QRCodeWriter;
import com.wmh.baseservice.common.utils.encrypt.RSAUtil;
import com.wmh.baseservice.common.utils.upload.service.CosService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * 二维码生成工具
 */
@Component
public class QrCodeUtil {

    @Resource
    private WxMaService wxMaService;

    @Resource
    private CosService cosService;

    private static WxMaService staticWxMaService;

    @PostConstruct
    public void init() {
        staticWxMaService = wxMaService;
    }


    /**
     * 普通二维码
     *
     * @param params 二维码携带的参数
     * @param url    保存路径
     * @param name   文件名称
     */
    public static String createParamsQrCode(String params, String url, String name) throws Exception {
        String basePath = PathUtil.COS_DOMAIN + url + name + ".png";
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(RSAUtil.encryptByPublicKey(params), BarcodeFormat.QR_CODE, 500, 500);
        String pathUrl = PathUtil.getFullRealPath() + url + name;
        String filePath = pathUrl + ".png";
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        Path path = FileSystems.getDefault().getPath(filePath);
        MatrixToImageWriter.writeToPath(bitMatrix, "png", path);
        return basePath;
    }

    /**
     * 生成订单二维码, 并上传至COS对象存储
     * @param orderNo 订单编号
     * @param userId 用户id
     * @return 返回二维码图片url
     */
    public String generateAndUploadQrCode(String orderNo, Long userId) throws Exception {
        // 加密订单信息
        JSONObject object = new JSONObject(true);
        object.put("orderNo", orderNo);
        object.put("userId", userId);
        String encryptedInfo = RSAUtil.encryptByPublicKey(object.toJSONString());

        // 生成二维码
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(encryptedInfo, BarcodeFormat.QR_CODE, 500, 500);

        // 保存临时文件
        File tempFile = File.createTempFile("qr_", ".png");
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", tempFile.toPath());

        // 读取文件为字节数组
        byte[] data = Files.readAllBytes(tempFile.toPath());

        // 上传到COS
        String cosPath = "qr_codes/" + orderNo + ".png"; // 在COS中的路径
        String upload = cosService.upload(data, cosPath);

        // 删除临时文件
        tempFile.delete();

        // 返回COS中的图片URL
        return PathUtil.COS_DOMAIN + upload;
    }

    /**
     * 解析二维码
     * @param qrCodeData 二维码数据
     * @return 返回订单号和用户id
     */
    public String parsingQrCodes(String qrCodeData) throws Exception {
        // 解密二维码数据
        String decryptedData = RSAUtil.decryptByPrivateKey(qrCodeData);
        JSONObject jsonObject = JSON.parseObject(decryptedData);
        String orderNo = jsonObject.getString("orderNo");
        long userId = jsonObject.getLongValue("userId");
        return "order: " + orderNo + "userId: " + userId;
    }

    /**
     * 查看图片是否为二维码
     * @param bufferedImage 图片文件
     * @return 返回是否为二维码
     */
    public static boolean isQRCodeImage(BufferedImage bufferedImage) {
        try {
            LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Reader reader = new QRCodeMultiReader();
            reader.decode(bitmap);
            return true; // 解码成功，是二维码
        } catch (Exception e) {
            // 解码失败，不是二维码
            return false;
        }
    }

    /**
     * 获取微信小程序二维码，响应给客户端
     *
     * @param params   二维码携带的参数,为null则无参数
     * @param pagePath 扫码二维码需要跳转的微信页面
     */
    public static void getQrCode(HttpServletResponse response, String params, String pagePath) throws WxErrorException, IOException {
        // 获取小程序二维码生成实例
        WxMaQrcodeService wxMaQrcodeService = staticWxMaService.getQrcodeService();
        // 设置小程序二维码线条颜色为黑色
        WxMaCodeLineColor lineColor = new WxMaCodeLineColor("0", "0", "0");
        byte[] qrCodeBytes;
        if (CommUtil.checkNull(params)) {
            qrCodeBytes = wxMaQrcodeService.createWxaCodeUnlimitBytes(params, pagePath, 430, false, lineColor, false);
        } else {
            //该方式生成二维码总共只有10w，仅供测试调用
            qrCodeBytes = wxMaQrcodeService.createWxaCodeBytes(pagePath, 430, false, lineColor, false);
        }
        // 设置contentType
        response.setContentType("image/png");
        // 写入response的输出流中
        OutputStream stream = response.getOutputStream();
        stream.write(qrCodeBytes);
        stream.flush();
        stream.close();
    }

    /**
     * 获取微信小程序二维码并保存到本地
     *
     * @param params   二维码携带的参数,为null则无参数
     * @param filePath 本地保存路径
     * @param pagePath 扫码二维码需要跳转的微信页面
     */
    public static String getQrCodeSave(String params, String filePath, String pagePath) throws WxErrorException, IOException {
        // 获取小程序二维码生成实例
        WxMaQrcodeService wxMaQrcodeService = staticWxMaService.getQrcodeService();
        // 设置小程序二维码线条颜色为黑色
        WxMaCodeLineColor lineColor = new WxMaCodeLineColor("82", "167", "254");
        byte[] qrCodeBytes;
        if (CommUtil.checkNull(params)) {
            qrCodeBytes = wxMaQrcodeService.createWxaCodeUnlimitBytes(params, pagePath, 430, false, lineColor, false);
        } else {
            //该方式生成二维码总共只有10w，仅供测试调用
            qrCodeBytes = wxMaQrcodeService.createWxaCodeBytes(pagePath, 430, false, lineColor, false);
        }
        String url = PathUtil.getFullRealPath() + filePath;
        File file = new File(url);
        if (!file.exists()) {
            file.mkdirs();
        }
        //文件写出
        String fileName = UUIDUtil.getTimeId() + ".png";
        String realPath = url + "/" + fileName;
        FileOutputStream fileOutputStream = new FileOutputStream(realPath);
        fileOutputStream.write(qrCodeBytes);
        fileOutputStream.flush();
        fileOutputStream.close();
        return realPath;
    }
}
